<?php
/**
 * php GEM Project
 * 
 * LICENSE
 * 
 * PHP System Architecture Enabling Rapid Application Deployment and Scalability
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @copyright Copyright (C) 2010 Zeletron LLC (http://zeletron.com)
 * @license http://gem.zeletron.com/license
 */

/*
 * GEM/Form/Form.php
 * 
 * This class extends Zend_Form with persistance
 * capabilities. If you need to persist form data,
 * try extending this class rather than Zend_Form.
 * 
 * @author David Joly
 * @link http://zeletron.com
 * 
 * @category GEM
 * @package GEM_Form
 */
class GEM_Form_Form extends Zend_Form
{
	/**
	 * The form name (Must be set in extending class!)
	 * 
	 * @var string
	 */
	protected $_formName;
	
	/**
	 * Forms fields to populate with error messages when 
	 * persisting error messages.
	 * 
	 * @var array
	 */
	protected $_messagePersistingFields = array();
	
	/**
	 * Form fields to populate with data when persisting
	 * data.
	 * 
	 * @var array
	 */
	protected $_valuePersistingFields = array();
	
	/**
	 * Returns the form's name
	 * 
	 * @return string
	 */
	public function getFormName(){
		return $this->_formName;
	}
	
	/**
	 * Overloads Zend_Form's empty persistData() method.
	 * Will save data and error messages to the session
	 * for retrieval.
	 * 
	 * @return void
	 */
	public function persistData(){
		$ns = new Zend_Session_Namespace($this->_formName);
		$messages = array();
		foreach($this->_messagePersistingFields as $field){
			$messages[$field] = $this->getElement($field)->getMessages();
		}
		$values = array();
		foreach($this->_valuePersistingFields as $field){
			$values[$field] = $this->getElement($field)->getValue();
		}
		$ns->values = $values;
		$ns->messages = $messages;
	}
	
	/**
	 * The name or form element object that should persist
	 * error messages.
	 * 
	 * @param string | Zend_Form_Element $field
	 * @return GEM_Form | Provides Fluent Interface
	 */
	public function addMessagePersistingField($field){
		if(is_string($field)){
			$element = $this->getElement($field);
		} elseif($field instanceof Zend_Form_Element){
			$element = $field;
		} else {
			throw GEM_Form_Exception(__METHOD__ . ' expects a valid Zend_Form_Element object.');
		}
		$this->_messagePersistingFields[] = $element->getName();
		return $this;
	}
	
	/**
	 * The name or form element object that should persist
	 * data.
	 * 
	 * @param string | Zend_Form_Element $field
	 * @return GEM_Form | Provides Fluent Interface
	 */
	public function addValuePersistingField($field){
		if(is_string($field)){
			$element = $this->getElement($field);
		} elseif($field instanceof Zend_Form_Element){
			$element = $field;
		} else {
			throw GEM_Form_Exception(__METHOD__ . 'expects a valid Zend_Form_Element object.');
		}
		$this->_valuePersistingFields[] = $element->getName();
		return $this;
	}
	
	/**
	 * Clears current fields set to persist messages with specified fields.
	 * Expects an array of field/element names or Zend_Form_Element objects.
	 * 
	 * @param array $fields
	 * @return GEM_Form | Provides Fluent Interface
	 */
	public function setMessagePersistingFields(array $fields = array()){
		$this->_messagePersistingFields = array();
		foreach($fields as $field){
			$this->addMessagePersistingField($field);
		}
		return $this;
	}
	
	/**
	 * Clears current fields set to persist values with specified fields.
	 * Expects an array of field/element names or Zend_Form_Element objects.
	 * 
	 * @param array $fields
	 * @return GEM_Form | Provides Fluent Interface
	 */
	public function setValuePersistingFields(array $fields = array()){
		$this->_valuePersistingFields = array();
		foreach($fields as $field){
			$this->addValuePersistingField($field);
		}
		return $this;
	}
	
	/**
	 * Populates the form with persisted error messages and
	 * data.
	 * 
	 * @return void
	 */
	protected function _populatePersistedData(){
		if(Zend_Session::namespaceIsset($this->_formName)){
			$ns = new Zend_Session_Namespace($this->_formName);
			//Add error messages if they exist
			if(isset($ns->messages)){
				foreach($ns->messages as $element => $messages){
					$this->getElement($element)->setErrors($messages);
				}
			}
			//Populate form values
			if(isset($ns->values)){
				$this->populate($ns->values);
			}
			//Clear namespace
			Zend_Session::namespaceUnset($this->_formName);

		}
	}
}